/*
 * Copyright (c) 2006-2011, Petr Panteleyev
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 *    1. Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *    2. Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *    3. The name of the author may not be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.panteleyev.livejournal;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.io.IOException;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JRadioButton;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;

import org.panteleyev.blogclient.BloggerFrame;
import org.panteleyev.blogclient.MainClass;
import org.panteleyev.blogclient.ProfileDialog;
import org.panteleyev.blogclient.UserProfileManager;
import org.panteleyev.ljapi.LJCommentCacheInfo;
import org.panteleyev.ljapi.LJCommentMetaDataUpdate;
import org.panteleyev.swing.OkCancelButtonPanel;
import org.panteleyev.swing.SwingFactory;

public class LJProfileDialog extends ProfileDialog {
    private LJUserProfile profile;
    private int m_mask;

    // Controls
    private JTextField      profileNameEdit;
    private JTextField      userNameEdit;
    private JPasswordField  passwordEdit;
    private JTextField      serverEdit;
    private JCheckBox       storePasswordCheckBox;
    private JCheckBox       defaultProfileCheck;
    private JRadioButton    commOncePerSessionRadio;
    private JRadioButton    commEveryUpdateRadio;
    private JRadioButton    commNeverRadio;
    private JButton         clearCommMetaButton;
    private JButton         clearCommDataButton;
    private JPanel          checkFriendListPanel;
    private JCheckBox       checkFriendsCheckBox;
    private JRadioButton    checkAllRadio;
    private JRadioButton    checkSelectedRadio;
    private JCheckBox       remindBirthdaysCheck;
    private JTextField      remindDaysCountEdit;
    private JButton         checkGroupsButton;
    private JLabel          groupsLabel;
    private JLabel          remindDaysLabelPrefix;
    private JLabel          remindDaysLabelSuffix;

    /**
     * Creates new form LJProfileDialog
     * @param parent
     * @param prof
     */
    public LJProfileDialog(BloggerFrame parent, LJUserProfile prof) {
        super(parent);
        initComponents();

        profile = prof;
        m_mask = profile.getCheckFriendsMask();

        if (profile.getServer().length() == 0) {
            serverEdit.setText(LJServers.getDefaultServerName());
        } else {
            serverEdit.setText(profile.getServer());
        }

        profileNameEdit.setText(profile.getName());

        boolean b = profile.getStorePasswd();
        storePasswordCheckBox.setSelected(b);
        passwordEdit.setEnabled(b);
        if (b) {
            passwordEdit.setText(profile.getHPasswd());
        } else {
            passwordEdit.setText("");
        }

        userNameEdit.setText(profile.getUserName());
        defaultProfileCheck.setSelected(profile.isDefaultProfile());

        switch (profile.getCommentsMetaInfoUpdate()) {
            case ONCE:
                commOncePerSessionRadio.setSelected(true);
                break;
            case ON_UPDATE:
                commEveryUpdateRadio.setSelected(true);
                break;
            case NEVER:
                commNeverRadio.setSelected(true);
                break;
        }

        /* Check if we are logged with the same profile as being edited */
        boolean bConnected = profile.isConnected();

        clearCommMetaButton.setEnabled(!bConnected);
        clearCommDataButton.setEnabled(!bConnected);

        if (bConnected) {
            checkFriendListPanel.setVisible(true);
            checkFriendsCheckBox.setSelected(profile.getCheckFriends());
            if (m_mask == 1) {
                checkAllRadio.setSelected(true);
            } else {
                checkSelectedRadio.setSelected(true);
            }
        } else {
            checkFriendListPanel.setVisible(false);
        }

        remindBirthdaysCheck.setSelected(profile.getRemindBirthdays());
        remindDaysCountEdit.setText(Integer.toString(profile.getRemindBirthdaysInterval()));
        enableFriendControls();

        pack();
    }

    private void initComponents() {
        setTitle(TITLE);
        getContentPane().setLayout(new BorderLayout());

        JLabel l1, l2, l3, l4;
        JPanel p1, p2, p3, p4;
        JPanel mainPanel = SwingFactory.createPanel(BorderFactory.createEmptyBorder(5, 5, 5, 5), SwingFactory.LAYOUT.BOX_Y,
            p1 = SwingFactory.createPanel(null, SwingFactory.LAYOUT.BOX_X,
                l1 = new JLabel(PROFILE_NAME_LABEL),
                Box.createHorizontalStrut(3),
                profileNameEdit = new JTextField(20)
            ),
            Box.createVerticalStrut(3),
            p2 = SwingFactory.createPanel(null, SwingFactory.LAYOUT.BOX_X,
                l2 = new JLabel(USER_NAME_LABEL),
                Box.createHorizontalStrut(3),
                userNameEdit = new JTextField(20)
            ),
            Box.createVerticalStrut(3),
            p3 = SwingFactory.createPanel(null, SwingFactory.LAYOUT.BOX_X,
                l3 = new JLabel(SERVER_LABEL),
                Box.createHorizontalStrut(3),
                serverEdit = new JTextField(10)
            ),
            Box.createVerticalStrut(3),
            p4 = SwingFactory.createPanel(null, SwingFactory.LAYOUT.BOX_X,
                l4 = new JLabel(PASSWORD_LABEL),
                Box.createHorizontalStrut(3),
                passwordEdit = new JPasswordField(20)
            ),
            Box.createVerticalStrut(3),
            storePasswordCheckBox = new JCheckBox(new AbstractAction(REMEMBER_PASSWORD_CHECKBOX) {
                @Override
                public void actionPerformed(ActionEvent e) {
                    boolean en = storePasswordCheckBox.isSelected();
                    passwordEdit.setEnabled(en);
                }
            }),
            Box.createVerticalStrut(3),
            defaultProfileCheck = new JCheckBox(MAKEDEFAULT_CHECKBOX),
            Box.createVerticalGlue()
        );

        serverEdit.setEditable(false);
        SwingFactory.setAlignmentX(mainPanel, LEFT_ALIGNMENT);
        SwingFactory.setCommonPreferredSize(l1, l2, l3, l4);
        SwingFactory.setHeightMaximumToPreferred(p1, p2, p3, p4);

        JPanel friendsPanel = SwingFactory.createPanel(BorderFactory.createEmptyBorder(5, 5, 5, 5), SwingFactory.LAYOUT.BOX_Y,
            checkFriendListPanel = SwingFactory.createPanel(null, SwingFactory.LAYOUT.BOX_Y,
                checkFriendsCheckBox = new JCheckBox(new AbstractAction(L10N.LJPROF_DIALOG_CHECK_FRIENDS_CHECKBOX.s()) {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        enableFriendControls();
                    }
                }),
                p1 = SwingFactory.createPanel(null, SwingFactory.LAYOUT.BOX_X,
                    groupsLabel = new JLabel(L10N.LJPROF_DIALOG_GROUPS_LABEL.s()),
                    Box.createHorizontalStrut(3),
                    checkAllRadio = new JRadioButton(new AbstractAction(L10N.LJPROF_DIALOG_CHECK_ALL_RADIO.s()) {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            m_mask = 1;
                            checkGroupsButton.setEnabled(false);
                        }
                    }),
                    Box.createHorizontalStrut(3),
                    checkSelectedRadio = new JRadioButton(new AbstractAction(L10N.LJPROF_DIALOG_CHECK_SELECTED_RADIO.s()) {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            checkGroupsButton.setEnabled(true);
                            selectGroups();
                        }
                    }),
                    Box.createHorizontalStrut(3),
                    checkGroupsButton = new JButton(new AbstractAction("...") {
                        @Override
                        public void actionPerformed(ActionEvent e) {
                            selectGroups();
                        }
                    })
                )
            ),
            Box.createVerticalStrut(5),
            p2 = SwingFactory.createPanel(null, SwingFactory.LAYOUT.BOX_X,
                remindBirthdaysCheck = new JCheckBox(new AbstractAction(L10N.LJPROF_DIALOG_REMIND_BIRTHDAYS_CHECKBOX.s()) {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        enableFriendControls();
                    }
                }),
                Box.createHorizontalStrut(5),
                remindDaysLabelPrefix = new JLabel(L10N.LJPROF_DIALOG_DAYS_PREFIX.s()),
                Box.createHorizontalStrut(3),
                remindDaysCountEdit = new JTextField(2),
                Box.createHorizontalStrut(3),
                remindDaysLabelSuffix = new JLabel(L10N.LJPROF_DIALOG_DAYS_POSTFIX.s())
            )
        );

        ButtonGroup bGroup = new ButtonGroup();
        bGroup.add(checkSelectedRadio);
        bGroup.add(checkAllRadio);

        SwingFactory.setAlignmentX(checkFriendListPanel, LEFT_ALIGNMENT);
        SwingFactory.setAlignmentX(friendsPanel, LEFT_ALIGNMENT);
        SwingFactory.setWidthMaximumToPreferred(remindDaysCountEdit);
        SwingFactory.setHeightMaximumToPreferred(p1, p2);

        JPanel commentsPanel = SwingFactory.createPanel(BorderFactory.createEmptyBorder(5, 5, 5, 5), SwingFactory.LAYOUT.BOX_Y,
            SwingFactory.createPanel(BorderFactory.createTitledBorder(L10N.LJPROF_DIALOG_UPDATE_COMMENTS_BORDER.s()), SwingFactory.LAYOUT.BOX_Y,
                commOncePerSessionRadio = new JRadioButton(L10N.LJPROF_DIALOG_ONCE_RADIO.s()),
                Box.createVerticalStrut(3),
                commEveryUpdateRadio = new JRadioButton(L10N.LJPROF_DIALOG_EVERY_UPDATE_RADIO.s() ),
                Box.createVerticalStrut(3),
                commNeverRadio = new JRadioButton(L10N.LJPROF_DIALOG_NEVER_RADIO.s())
            ),
            Box.createVerticalStrut(5),
            clearCommMetaButton = new JButton(new AbstractAction(L10N.LJPROF_DIALOG_CLEAR_INFO_BUTTON.s()) {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (MainClass.showConfirmDialog(null)) {
                        profile.clearMetaData();
                        try {
                            LJCommentCacheInfo info = profile.loadCommentsInfo();
                            info.resetMaxID();
                            profile.storeCommentsInfo(info);
                        } catch (IOException | ClassNotFoundException ex) {
                            MainClass.handleException(null, ex);
                        }
                    }
                }
            }),
            Box.createVerticalStrut(5),
            clearCommDataButton = new JButton(new AbstractAction(L10N.LJPROF_DIALOG_CLEAR_COMMENTS_BUTTON.s()) {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (MainClass.showConfirmDialog(null)) {
                        profile.clearComments();
                        try {
                            LJCommentCacheInfo info = profile.loadCommentsInfo();
                            info.resetMaxDownloadedID();
                            profile.storeCommentsInfo(info);
                        } catch (IOException | ClassNotFoundException ex) {
                            MainClass.handleException(null, ex);
                        }
                    }
                }
            })
        );

        bGroup = new ButtonGroup();
        bGroup.add(commOncePerSessionRadio);
        bGroup.add(commEveryUpdateRadio);
        bGroup.add(commNeverRadio);

        JTabbedPane pane = new JTabbedPane();
        pane.add(L10N.LJPROF_DIALOG_MAIN_TAB_TITLE.s(), mainPanel);
        pane.add(L10N.LJPROF_DIALOG_FRIENDS_TAB_TITLE.s(), friendsPanel);
        pane.add(L10N.LJPROF_DIALOG_COMMENTS_TAB_TITLE.s(), commentsPanel);

        getContentPane().add(pane, BorderLayout.CENTER);
        getContentPane().add(new OkCancelButtonPanel(this), BorderLayout.SOUTH);
    }

    private void enableFriendControls() {
        if (checkFriendsCheckBox.isSelected()) {
            checkAllRadio.setEnabled(true);
            checkSelectedRadio.setEnabled(true);
            groupsLabel.setEnabled(true);
            checkGroupsButton.setEnabled(m_mask != 1);
        } else {
            checkAllRadio.setEnabled(false);
            checkSelectedRadio.setEnabled(false);
            checkGroupsButton.setEnabled(false);
            groupsLabel.setEnabled(false);
        }

        final boolean b = remindBirthdaysCheck.isSelected();
        remindDaysCountEdit.setEnabled(b);
        remindDaysLabelPrefix.setEnabled(b);
        remindDaysLabelSuffix.setEnabled(b);
    }

    @Override
    public boolean showDialog() {
        boolean res = super.showDialog();
        if (res) {
            profile.setName(profileNameEdit.getText());

            if (storePasswordCheckBox.isSelected()) {
                String newPasswd = new String(passwordEdit.getPassword());
                if (!profile.getStorePasswd() || !newPasswd.equals(profile.getHPasswd())) {
                    profile.setPassword(newPasswd);
                }

                profile.setStorePasswd(true);
            } else {
                profile.setStorePasswd(false);
                profile.setPassword("");
            }

            final boolean remindBirthdays = remindBirthdaysCheck.isSelected();
            profile.setRemindBirthdays(remindBirthdaysCheck.isSelected());
            if (remindBirthdays) {
                int bDays = 0;
                try {
                    bDays = Integer.parseInt(remindDaysCountEdit.getText());
                }
                catch (NumberFormatException e) {
                    bDays = 3;
                }
                if (bDays < 0) {
                    bDays = 3;
                }

                profile.setRemindBirthdaysInterval(bDays);
            }

            if (commOncePerSessionRadio.isSelected()) {
                profile.setCommentsMetaInfoUpdate(LJCommentMetaDataUpdate.ONCE);
            } else {
                if (commEveryUpdateRadio.isSelected()) {
                    profile.setCommentsMetaInfoUpdate(LJCommentMetaDataUpdate.ON_UPDATE);
                } else {
                    profile.setCommentsMetaInfoUpdate(LJCommentMetaDataUpdate.NEVER);
                }
            }
            profile.setDefaultProfile(defaultProfileCheck.isSelected());

            profile.setCheckFriends(checkFriendsCheckBox.isSelected());
            profile.setCheckFriendsMask(m_mask);
        }
        return res;
    }

    private void selectGroups() {
        /* Check if we are logged with the same profile as being edited */
        GroupMaskDialog dial = new GroupMaskDialog(getMainFrame(), profile.getAccount(), m_mask);
        if (dial.showDialog()) {
            m_mask = dial.getMask();
        } else {
            if (m_mask == 1) {
                checkAllRadio.setSelected(true);
                enableFriendControls();
            }
        }
    }

    @Override
    protected void onOk() {
        String msg = UserProfileManager.checkProfileName(profileNameEdit.getText(), profile);
        if (msg != null) {
            JOptionPane.showMessageDialog(getMainFrame(), msg, "Error", JOptionPane.ERROR_MESSAGE);
        } else {
            super.onOk();
        }
    }
}
